package com.triple.triplerpc.server.tcp;

import com.triple.triplerpc.model.RpcRequest;
import com.triple.triplerpc.model.RpcResponse;
import com.triple.triplerpc.protocol.ProtocolMessage;
import com.triple.triplerpc.protocol.ProtocolMessageDecoder;
import com.triple.triplerpc.protocol.ProtocolMessageEncoder;
import com.triple.triplerpc.protocol.ProtocolMessageTypeEnum;
import com.triple.triplerpc.registry.LocalRegistry;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetSocket;

import java.io.IOException;
import java.lang.reflect.Method;

/**
 * TCP 请求处理器
 * 1. 解码 buffer 为对象，并从对象中获取参数。
 * 2. 根据服务名称从本地注册器中获取到对应的服务实现类。
 * 3. 通过反射机制调用方法，得到返回结果。
 * 4. 对返回结果进行封装和序列化，并写入到响应中。
 */
public class TcpServerHandler implements Handler<NetSocket> {

    @Override
    public void handle(NetSocket netSocket) {
        System.out.println("7. 处理消费者请求 - TCP 请求处理器");
        // 装饰者模式: 使用RecordParser解决半包和粘包问题
        TcpBufferHandlerWrapper bufferHandlerWrapper = new TcpBufferHandlerWrapper(buffer -> {
            // 接受请求，解码
            ProtocolMessage<RpcRequest> protocolMessage;
            try {
                protocolMessage = (ProtocolMessage<RpcRequest>) ProtocolMessageDecoder.decode(buffer);
            } catch (IOException e) {
                throw new RuntimeException("协议消息解码错误");
            }
            RpcRequest rpcRequest = protocolMessage.getBody();
            // 记录日志
            System.out.println(" >>> 请求对象: " + rpcRequest.toString());

            // 响应结果对象
            RpcResponse rpcResponse = new RpcResponse();
            try {
                // 根据服务名称从本地注册器中获取到对应的服务实现类
                Class<?> implClass = LocalRegistry.get(rpcRequest.getServiceName());
                // 通过反射机制调用方法, 得到返回结果
                Method method = implClass.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
                Object result = method.invoke(implClass.newInstance(), rpcRequest.getArgs());
                // 对返回结果进行封装
                rpcResponse.setData(result);
                rpcResponse.setDataType(method.getReturnType());
                rpcResponse.setMessage("ok");
            } catch (Exception e) {
                e.printStackTrace();
                rpcResponse.setMessage(e.getMessage());
                rpcResponse.setException(e);
            }
            System.out.println(" >>> 编码前响应对象: " + rpcResponse);

            // 发送响应，编码
            ProtocolMessage.Header header = protocolMessage.getHeader();
            header.setType((byte) ProtocolMessageTypeEnum.RESPONSE.getKey());
            ProtocolMessage<RpcResponse> responseProtocolMessage = new ProtocolMessage<>(header, rpcResponse);
            try {
                Buffer encode = ProtocolMessageEncoder.encode(responseProtocolMessage);
                netSocket.write(encode);
            } catch (IOException e) {
                throw new RuntimeException("协议消息编码错误");
            }
            System.out.println(" >>> 请求处理完毕, 响应回消费者");
        });

        netSocket.handler(bufferHandlerWrapper);
    }

}
